﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Demo.Model;
using Microsoft.Win32;
using Thinktecture.DataForm;

namespace Demo.ViewModel
{
    public class PersonViewModel : ModelBase
    {
        public Window View { get; set; }
        private ObservableCollection<Person> _personList;
        private ICollectionView _persons;
        private Person _person;
        private IEditableCollectionView _personEditView;
        private ObservableCollection<Department> _departments;
        private ActionCommand _actionCommand;
        private DelegateCommand _saveCommand;
        private DelegateCommand _addCommand;
        private DelegateCommand _removeCommand;
        private DelegateCommand _selectionButtonCommand;
        private bool _hasError;

        public bool HasError
        {
            get { return _hasError; }
            set { _hasError = value; this.OnPropertyChanged("HasError"); }
        }

        public DelegateCommand SelectionButtonCommand
        {
            get { return _selectionButtonCommand; }
            set { _selectionButtonCommand = value; this.OnPropertyChanged("SelectionButtonCommand"); }
        }

        public ActionCommand ActionCommand
        {
            get { return _actionCommand; }
            set { _actionCommand = value; this.OnPropertyChanged("ActionCommand"); }
        }

        public DelegateCommand SaveCommand
        {
            get { return _saveCommand; }
            set { _saveCommand = value; this.OnPropertyChanged("SaveCommand"); }
        }

        public DelegateCommand AddCommand
        {
            get { return _addCommand; }
            set { _addCommand = value; this.OnPropertyChanged("AddCommand"); }
        }

        public DelegateCommand RemoveCommand
        {
            get { return _removeCommand; }
            set { _removeCommand = value; this.OnPropertyChanged("RemoveCommand"); }
        }

        public Person Person
        {
            get { return _person; }
            set { _person = value; this.OnPropertyChanged("Person"); }
        }

        public ICollectionView Persons
        {
            get { return _persons; }
            set { _persons = value; this.OnPropertyChanged("Persons"); }
        }

        public ObservableCollection<Department> Departments
        {
            get { return _departments; }
            set { _departments = value; this.OnPropertyChanged("Departments"); }
        }

        public void Initialize()
        {
            this.View = new DataFormWindow();
            this.View.DataContext = this;

            this.AddCommand = new DelegateCommand(this.CanExecuteAddCommand, this.ExecuteAddCommand);
            this.RemoveCommand = new DelegateCommand(this.CanExecuteRemoveCommand, this.ExecuteRemoveCommand);
            this.SaveCommand = new DelegateCommand(this.ExecuteSaveCommand);
            this.ActionCommand = new ActionCommand();
            this.SelectionButtonCommand = new DelegateCommand(this.CanExecuteSelectionButtonCommand, this.ExecuteSelectionButtonCommand);

            this.Departments = new ObservableCollection<Department>()
            {
                new Department { Name="Finance" },
                new Department { Name="Administration" },
                new Department { Name="Development" }
            };
            _personList = new ObservableCollection<Person>()
            {
                    new Person { Id = 1, Name = "Jörg Neumann", Birthday = new DateTime(1971, 7, 29), Department = this.Departments[2], Image=new BitmapImage(new Uri("/Demo;component/Images/jone_130x160.png", UriKind.Relative)) },
                    new Person { Id = 2, Name = "Bob Miller", Birthday = new DateTime(1969, 2, 6), Department = this.Departments[0] },
            };
            _personList.CollectionChanged += new NotifyCollectionChangedEventHandler(OnCollectionChanged);
            var view = new CollectionViewSource() { Source = _personList };
            this.Persons = view.View;
            _personEditView = view.View as IEditableCollectionView;
            var a = new ListCollectionView(_personList);
            this.Person = _personList[0];
            this.View.ShowDialog();
        }

        private void ExecuteSaveCommand(object parameter)
        {
            if (!this.HasError)
            {
                this.ActionCommand.ExecuteAction(DataFormAction.AcceptChanges, null);
                this.ActionCommand.ExecuteAction(DataFormAction.SetBusy, null);
                ThreadPool.QueueUserWorkItem(o =>
                    {
                        Thread.Sleep(5000);
                        Application.Current.Dispatcher.Invoke(
                            DispatcherPriority.Background,
                            new ThreadStart(() =>
                                this.ActionCommand.ExecuteAction(DataFormAction.SetAvailable, null)));
                    });
            }
        }

        private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null && e.NewItems.Count > 0)
                ((Person)e.NewItems[0]).Id = 10;
        }

        private bool CanExecuteAddCommand(object parameter)
        {
            return true;
        }

        private void ExecuteAddCommand(object parameter)
        {
            _personEditView.AddNew();
        }

        private bool CanExecuteRemoveCommand(object parameter)
        {
            return ((Person)_persons.CurrentItem).Id > 0;
        }

        private void ExecuteRemoveCommand(object parameter)
        {
            if (_personEditView.IsAddingNew)
                _personEditView.CancelNew();
            else
                _personEditView.Remove(_persons.CurrentItem);
        }

        private bool CanExecuteSelectionButtonCommand(object parameter)
        {
            return true;
        }

        private void ExecuteSelectionButtonCommand(object parameter)
        {
            var dialog = new OpenFileDialog();
            dialog.Title = Properties.Resources.PersonSelectImageDialogText;
            dialog.Filter = Properties.Resources.PersonSelectImageDialogFilter;
            if (dialog.ShowDialog().Value)
            {
                ((Person)_persons.CurrentItem).Image = new BitmapImage(
                    new Uri("file://" + dialog.FileName));
            }
        }
    }
}
